package link.wangkui.lamda.stream;

import link.wangkui.lamda.convenient.reference.MyConsumer;
import link.wangkui.lamda.convenient.reference.Person;
import link.wangkui.lamda.convenient.reference.Something;

import java.util.Comparator;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class FunctionalInterface {
    public static void main(String[] args) {
        // 1. Predicate 断言
        // Predicate 是一个可以指定入参类型，并返回 boolean 值的函数式接口。
        // 它内部提供了一些带有默认实现的方法，可以 被用来组合一个复杂的逻辑判断（and, or, negate）：
        Predicate<String> predicate = (s) -> s.length() > 0;

        boolean foo0 = predicate.test("foo");
        // true
        boolean foo1 = predicate.negate().test("foo");
        // negate否定相当于!true

        Predicate<Boolean> nonNull = Objects::nonNull;
        Predicate<Boolean> isNull = Objects::isNull;

        Predicate<String> isEmpty = String::isEmpty;
        Predicate<String> isNotEmpty = isEmpty.negate();


        //Functions
        //Function 函数式接口的作用是，我们可以为其提供一个原料，他给生产一个最终的产品。
        // 通过它提供的默认方法，组合,链行处理(compose, andThen)：
        Function<String, Integer> toInteger = Integer::valueOf;
        //转Integer
        Function<String, String> backToString = toInteger.andThen(String::valueOf);
        //转String
        Function<String, String> afterToStartsWith = backToString.andThen(new Something()::startsWith);
        //截取第一位
        String apply = afterToStartsWith.apply("123");
        // "123"
        System.out.println(apply);

        // Suppliers
        // Supplier 与 Function 不同，它不接受入参，直接为我们生产一个指定的结果，
        // 有点像生产者模式：
        Supplier<Person> personSupplier0 = Person::new;
        personSupplier0.get();   // new Person
        Supplier<String> personSupplier1 = Something::test01;
        //这个test方法是静态的，且无入参
        personSupplier1.get();
        // hi
        Supplier<String> personSupplier2 = new Something()::test02;


        // 参照物，方便知道下面的Lamdba表达式写法
        Consumer<Person> greeter01 = new Consumer<Person>() {
            @Override
            public void accept(Person p) {
                System.out.println("Hello, " + p.getFirstName());
            }
        };
        Consumer<Person> greeter02 = (p) -> System.out.println("Hello, " + p.getFirstName());
        greeter02.accept(new Person("Luke", "Skywalker"));
        //Hello, Luke
        Consumer<Person> greeter03 = new MyConsumer<Person>()::accept;
        // 也可以通过定义类和方法的方式去调用，这样才是实际开发的姿势
        greeter03.accept(new Person("Luke", "Skywalker"));
        //Hello, Luke

         // Comparators
        // Comparator 在 Java 8 之前是使用比较普遍的。
        // Java 8 中除了将其升级成了函数式接口，还为它拓展了一些默认方法：
        Comparator<Person> comparator01 = (p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName());
        Comparator<Person> comparator02 = Comparator.comparing(p -> p.getFirstName());
        //等同于上面的方式
        Person p1 = new Person("John", "Doe");
        Person p2 = new Person("Alice", "Wonderland");
        comparator01.compare(p1, p2);
        // > 0
        comparator02.reversed().compare(p1, p2);
        // < 0
    }
}
